package org.liang.factory.excel;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;
import org.liang.factory.bean.BeanAttrsInfo;
import org.liang.factory.bean.BeanInfo;
import org.liang.factory.config.ClassConfig;

public abstract class CreateExampleExcel {
	private static ClassConfig CONFIG_G = null;//全局配置信息
	private static boolean isReadRow = false;//是否需要读取的行
	
	public static List<BeanInfo> readExcelData(ClassConfig config) {
		
		CONFIG_G = config;
		String excelPath = config.filePath;
		int[] sheets = config.sheets;
		Workbook wb = getWorkbook(excelPath);
		if(wb==null) {
			return null;
		}
		//初始化读取的sheets
		int sheetNum = wb.getNumberOfSheets();
		if (sheets == null) {
			sheets = new int[sheetNum];
			for (int i = 0; i < sheetNum; i++) {
				sheets[i] = i;
			}
		}
		//生成javaCode对象
		List<BeanInfo> list = new ArrayList<BeanInfo>();
		for (int i = 0; i < sheets.length; i++) {
			int n = sheets[i];
			if (n > sheetNum) {
				continue;
			}
			Sheet sheet = wb.getSheetAt(n); // 获取第一个sheet表
			String sheetName = sheet.getSheetName();
			System.out.println("sheetName：" + sheetName);
			List<BeanInfo> listTemp = readSheet(sheet);
			list.addAll(listTemp);
		}
		
		try {
			wb.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		
		return list;
	}

	private static List<BeanInfo> readSheet(Sheet sheet) {
		List<BeanInfo> list = new ArrayList<BeanInfo>();
		List<BeanAttrsInfo> attrList = new ArrayList<BeanAttrsInfo>();//属性
		Set<String> pgs = new HashSet<String>();//导入包
		BeanInfo beanInfo = new BeanInfo();//javaBean对象
		int lastNum = sheet.getLastRowNum();

		for (int i = 0; i <= lastNum; i++) {
			Row rowData = sheet.getRow(i);//读取行

			try {
				if(rowData == null) {
					continue;
				}
				String startFlag = isStartFlag(rowData);

				if (isReadRow && "start".equals(startFlag)) {
					
					boolean isOverride = false;//是否覆盖javaCode，默认不覆盖
					
					Object cell9 = getCellValue(rowData.getCell(9));
					if (cell9 != null) {
						isOverride = (Boolean) cell9;
					}
					
					Object cell11 = getCellValue(rowData.getCell(11));
					if (cell11 != null) {
						CONFIG_G.packageName = cell11.toString();
					}
					
					
					String className = getCellValue(rowData.getCell(0)).toString() + CONFIG_G.classSuffix;
					String classComment = getCellValue(rowData.getCell(1)).toString();
					beanInfo = new BeanInfo();
					beanInfo.setClassName(className);
					beanInfo.setClassComment(classComment);
					beanInfo.setAuthor(CONFIG_G.author);
					beanInfo.setClassPackage(CONFIG_G.packageName);
					
					String path = CONFIG_G.createPath;
					if(StringUtils.isBlank(path)) {
						File f = new File("");
						path = f.getAbsolutePath()+"\\src\\main\\java";
					}
					beanInfo.setClassPath(path);
					beanInfo.cover = isOverride;
					attrList.clear();
					pgs.clear();
				}else if(!isReadRow && "end".equals(startFlag)) {
					
					addBeanAttrs(rowData,attrList);//读取行，并添加属性
					beanInfo.setAttrList(attrList);
					beanInfo.setImportPackage(pgs);
					
					BeanInfo clone = beanInfo.clone();
					list.add(clone);
				}else if(isReadRow) {
					addBeanAttrs(rowData,attrList);//读取行，并添加属性
				}

			} catch (Exception e) {
				System.err.println("第" + (i+1) + "行异常，异常信息：");
				e.printStackTrace();
				throw new RuntimeException();
			}

		}

		return list;
	}
	
	private static void addBeanAttrs(Row rowData,List<BeanAttrsInfo> attrList) {
		String proName = getCellValue(rowData.getCell(0)).toString();
		if ("参数".equals(proName)) {
			return;
		}
		//忽略
		Object obj = getCellValue(rowData.getCell(10));
		if(obj != null) {
			boolean isIg = (Boolean) obj;
			if(isIg) {
				return;
			}
		}
		//是否首字母转换小写
		if(CONFIG_G.firstToLowercase) {
			proName = proName.substring(0,1).toLowerCase() + proName.substring(1);
		}
		
		String proType = getCellValue(rowData.getCell(1)).toString().trim();
		proType = transType(proType);// 类型转换，对象+Dto，数组转换List，基本类型不变
		
		if("Int".equals(proType) || "Int16".equals(proType)) {
			proType="int";
		}

		String proDesc = getCellValue(rowData.getCell(3)).toString();
		Object proDesc2 = getCellValue(rowData.getCell(4));
		String comment = proDesc + (proDesc2 == null ? "" : proDesc2.toString().replaceAll("\r\n", "").replaceAll("\r", "").replaceAll("\n", ""));
		
		attrList.add(new BeanAttrsInfo(proName, proType, comment));
	}

	private static String isStartFlag(Row rowData) {
		Object startObj = getCellValue(rowData.getCell(8));
		if(startObj == null) {
			return null;
		}
		if("start".equals(startObj.toString())) {
			isReadRow=true;//开始读取数据行
			return "start";
		}else if("end".equals(startObj.toString())){
			isReadRow=false;//开始读取数据行
			return "end";
		}
		return null;
	}


	private static Object getCellValue(Cell cell) {
		Object object = null;
		if (cell == null) {
			return object;
		}
		switch (cell.getCellTypeEnum()) {
		case NUMERIC:
			object = cell.getNumericCellValue();
			break;
		case STRING:
			object = cell.getStringCellValue();
			break;
		case FORMULA:
			object = cell.getCellFormula();
			break;
		case BLANK:
			// object = cell.getStringCellValue();
			break;
		case BOOLEAN:
			object = cell.getBooleanCellValue();
			break;
		case ERROR:
			object = cell.getStringCellValue();
			break;
		default:
			System.out.println("wu");
			break;
		}
		return object;
	}

	private static String transType(String type) {
		if(noTransType(type)) {
			return type;
		}
		
		String t = type;
		if(type.indexOf("]") > 0) {//数组
			t = type.replace("[","").replace("]", "");
			boolean b = noTransType(t);
			if(b) {
				return type;
			}else {
				t=t+CONFIG_G.classSuffix+"[]";
			}
		}else {
			t=t+CONFIG_G.classSuffix;
		}
		return t;
	}
	
	/*
	 * 判断是否为基本类型，是返回true
	 */
	private static boolean noTransType(String type) {
		
		for (int i = 0; i < noTransTypes.length; i++) {
			if(noTransTypes[i].equalsIgnoreCase(type)) {
				return true;
			}
		}
		return false;
	}
	
	/**
	 * 
	 * @param excelPath 相对excel下的文件和绝对路径
	 * @return
	 */
	private static Workbook getWorkbook(String excelPath) {
		Workbook wb = null;
		try {
			if(StringUtils.isBlank(excelPath)) {
				System.err.println("文件名不能为空" + excelPath);
				return wb;
			}
			File f = null;
			if(excelPath.indexOf("/")==-1 && excelPath.indexOf("\\") == -1) {
				f= new File("src/main/resources/excel/"+excelPath);
			}else {
				f = new File(excelPath);
			}
			if(!f.exists()) {
				System.err.println("文件不存在" + f.getAbsolutePath());
				return wb;
			}
			
			InputStream is = new FileInputStream(f);//CreateExampleExcel.class.getClassLoader().getResourceAsStream("excel\\" + excelPath);
			wb = WorkbookFactory.create(is);// 这种方式 Excel 2003/2007/2010 都是可以处理的
		} catch (Exception e) {
			System.out.println("读取文件出错");
			e.printStackTrace();
		}

		return wb;
	}
	
	private static final String[] noTransTypes=new String[] {"String","int","double","list","date","boolean","int16"};//不需要转换类型
}
